<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN2">
<html>
<head>
<title>Strict Classloading</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <link href="http://dev.eclipse.org/default_style.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#ffffff">

<table width="100%">
<tr><td style="background:#0080C0"><b><span style="color:white">Proposal</span></b></td></tr>
</table>
<h1>Strict Classloading</h1>
<blockquote> 
  <p><b>Summary</b> <br>
  Eclipse embodies a component/modularity model. It allows plug-ins to express
    what they need of others (requiring plug-ins and importing packages) as well
    as what they contribute to others (providing/exporting packages). Ideally
  plug-ins would export/provide only that code which they consider to be API.
    Historically however the Eclipse plug-ins (and likely much of the community)
    have exported all of the code they contain. This is helpful to consumers
    living on the edge or pushing the envelope but it hinders both security as
    well as static API analysis done for security or performance optimization.
    Here we propose a path forward which allows plug-in producers to express their
    API and thus the runtime to enforce API-only consumption but still enables
    wild-men developers to access non-API on a selective basis.
  <p>Last
    Modified: December 16, 2004</p>
</blockquote>

<h2>Problem Definition</h2>
<p>Currently the Eclipse plug-ins expose all their code. The typical plugin.xml looks
  something like</p>
<pre>  &lt;plugin ...&gt;
    &lt;runtime&gt;<br>      &lt;library name=&quot;resources.jar&quot;&gt;<br><strong><font color="#FF0000">        &lt;export name=&quot;*&quot;/&gt;<br></font></strong>      &lt;/library&gt;<br>    &lt;/runtime&gt;
  &lt;/plugin&gt;</pre>
<p>The use of * in the export filter means that all classes in the related
  JAR are exposed to consumers. Typically these JARs contain both API and implementation
  classes.</p>
<p>Beyond the appalling aesthetics of exposing the non-API classes, there are a
  number of pragmatic reasons why this is bad. In particular, this practice inhibits
  runtime security and static analysis.</p>
<h3>Issue: Runtime Security</h3>
<p>Key to the Java security model is understanding and limiting the entry points
  to a piece of function. The security mechanisms are costly both at execution
  and development time. It is simply infeasible to secure every part of a large
  chunk of code like Eclipse if we have to consider all visible methods on all
  visible classes as entry points. Instead, we look to the API to provide a choke
  point
  through which all external access must go. If we secure the API then the implementation
  code need not be secured (or at least requires less work to secure). Of course,
  if you take this approach, the runtime must gurarantee that only the API types
  are visible to outside parties. To do this, there must be a clear, machine-readable
  description of these types in a plug-in.</p>
<h3>Issue: Static Analysis</h3>
<p>Static code analysis is increasingly interesting. It enables both security analysis
  and verification as well as performance optimizations such as code reduction
  and inlining. These analysis techniques begin by identifying the entry points
  in a body of code and then exhaustively traversing all execution paths. In
  the case of security analysis, the algorithm is looking for unsafe operations
  and places where permissions are required. For performance analysis the tools
  look for dead code (code which is not traversed), inlining opportunities and
  classes, methods and fields which can be obfuscated. Without an explicit and
  complete specification of the API, these analyses are not possible. </p>
<h3>Issue: Internal Type Access</h3>
<p>Historically Eclipse has not limited access to the internal classes of a plug-in.
  We define the API in Javadoc and warn programmers not to stray. This approach
  is weak and leads to component interaction via non-API routes. Enforcing API-only
  visibility eliminates this weakness. </p>
<p>Despite the pitfalls,
    some developers find it convenient or necessary to use internal classes.
  Some Eclipse plug-ins have been known to do this! In addition, various test
  suites
    rely on access to internal types to implement white-box tests. Simply cutting
    off this access is not friendly.</p>
<h3>Issue: Accurate Development-time Classpaths</h3>
<p>PDE builds development time classpaths from the exported packages it finds in
  the plug-ins it manages. Because Eclipse plug-ins typically export all their
  code, dependent plug-ins have all internal classes on their classpath at development
  time. This can lead to unintended use of internals through the convenience
  of code completion. Developers know there is a type called FooBar so type Foo&lt;ctrl&gt;&lt;space&gt;
  and choose from the results (or use Organize Imports). Because they find a
  type and things seem to work they are happy. Unfortunately, it is entirely
  possible that the FooBar used is not API since PDE has no way of telling the
  difference.</p>
<h2>Proposal</h2>
<p>Plug-in producers are in the best position to define their API. They clearly know
  the bounds of what they want to expose/support. Actually defining the
    API is not particularly challenging. The plugin.xml &lt;export name=&quot;&quot;/&gt; syntax
    and manifest.mf Export-Package: header both allow export specification. The
  specifications are given using an obvious and simple format. For example, the
  plugin.xml and manifest.mf markup (only one is needed) to expose the API for
  the Resource plug-in is shown below.</p>
<pre>  &lt;plugin ...&gt;
    &lt;runtime&gt;<br>      &lt;library name=&quot;resources.jar&quot;&gt;<br><strong><font color="#FF0000">        &lt;export name=&quot;org.eclipse.core.resources, org.eclipse.core.resources.refresh, 
            org.eclipse.core.resources.team&quot;/&gt;<br></font></strong>      &lt;/library&gt;<br>    &lt;/runtime&gt;
  &lt;/plugin&gt;</pre>
<pre>  <strong><font color="#FF0000">Export-Package: 
   org.eclipse.core.resources, 
   org.eclipse.core.resources.refresh, 
   org.eclipse.core.resources.team</font></strong>
</pre>
<h3>Defining the Exports</h3>
<p>The task of defining the exports is relatively straightforward. For most plug-ins
  it amounts to creating entries similar to those above. Notice that packages
  which are not to be exposed are simply not listed. Since Eclipse already uses
  package naming conventions for API packages, this process should take about
  5 minutes per Eclipse plug-in. Simply open the jar for a plug-in and note all
  of the API packages.
  List these packages in your choice of manifest (plugin.xml or manifest.mf).
  The effort required for non-Eclipse plug-ins which may not follow any package
  naming conventions may be slightly greater but is still quite minimal.</p>
<p>Note that classes used in executable extensions and Bundle.loadClass() do not
  need to be listed in the exports as they are loaded by asking the plug-in itself
  to
  load
the class rather than going through the normal classloader delegation mechanism.</p>
<p>Of course, if you are using non-API in someone else's plug-in you will have to
  either clean up your code or negotiate to have the required types exposed by
the prerequisite plug-in.</p>
<p>Notice also that there is a subtle difference between exposing a type and it
  being API. A type is not API simply because it is exported by a plug-in's manifest.
  plug-ins may be willing to expose types which are provisional API or specific
  types which are made available for targetted users (e.g, so-called SPI). The
  definition of API remains under this model. That is, the Javadoc is still the
final source.</p>
<h3>Exposing Internals (Strict mode)</h3>
<p><em>[Note: We need a better name here. &quot;strict mode&quot; is hard to negate (what is the
  opposite?). &quot;test mode&quot; is ok but has a wider connotation. Strict mode may
  in fact be one aspect of a supposed test mode but it likely does not cover
  all aspects.]</em></p>
<p>As mentioned in the problem definition, various people expect access to a wider
  range of classes. To support this we introduce a new (non-standard) OSGi manifest.mf
  header <em>Export-InternalPackage</em> and a <em>osgi.strictClassLoading</em> property for the framework. The Export-InternalPackage header has exactly the
  same syntax as Export-Package.</p>
<p>When the framework is in <em>strict mode</em> (i.e.,
  osgi.strictClassLoading = true), only types listed by the Export-Package headers
  are considered. When
    the framework is in <em>non-strict</em> mode (i.e., osgi.strictClassLoading
    = false), the elements on the Export-Package and Export-InternalPackage headers
    are merged (in that order) and considered by the runtime.</p>
<p>We do not propose any changes to the plugin.xml syntax. Developers using plugin.xml
  can specify their exports as outlined above and the manifest generator will
  automatically generate Export-InternalPackage header entries for all packages
  found in the plug-in but not included in the generated Export-Package header.
  Note however that the manifest.mf format offers additional power in filtering
  types from a package. Developers wishing to be more precise about their exports
  (sub-package control) can acheive this using the manifest.mf file.</p>
<p>By default Eclipse will default to non-strict mode (osgi.strictClassLoading =
  false) so as to increase compatibility. </p>
<p>As a bare minimum the Eclipse RCP plug-ins must operate correctly in strict mode.
  Optimally the entire Eclipse SDK will operate correctly in strict mode. </p>
<h3>Runtime/OSGi impact</h3>
<p>The OSGi code needs to support the strict mode flag. This impacts the following
  areas:</p>
<ul>
  <li><strong>Resolver:</strong> The code which gathers the list of exported packages
    now has to optionally gather elements from the Export-InternalPackage header.</li>
  <li><strong>State cache:</strong> The state cache change detection test needs to include a check that the strictness
    flag is the same as this affects the package wirings. If the strictness changes,
    the state cache needs to be flushed.</li>
</ul>
<h3>PDE UI impact</h3>
<p>PDE UI will need to expose the new export header in the appropriate way (e.g.,
in the package related editor pages). There are several things to note here</p>
<ul>
  <li>The Export-Package header allows includes/exclude filters to be
    specified. These should be exposed</li>
  <li>The ability to put a given package found in a bundle in either export list or
    explicitly not export it at all should be supported.</li>
  <li>PDE will likely have to retain a list of the packages and types
    which have
        been expressly NOT put on either the Export-Package or Export-InternalPackage
    headers. These are elements which the developer has decided to keep private
    in all cases. Maintaining this list is needed to differentiate between
    elements are not mentioned in either header because they are new
     or because they are to be private. The negative list can
     be kept in a separate manifest header (favoured) or though separate metadata
    (e.g., build.properties).</li>
</ul>
<p>PDE should offer the developer the option to use strict mode development-time
  classpaths. The semantics are the same here as putting the runtime in strict
  mode. That is, in strict mode only the Export-Package header is used where
  as in non-strict mode all exports are used. There may be an additional/related
  ability to add the Export-InternalPackage entries to the secondary classpath
for a plug-in project.</p>
<p>In any event, PDE should use the new JDT classpath includes/excludes capabilities
  to match the compiler classpath to the actual runtime classpath as close as
  possible.</p>
<h3>PDE Build impact</h3>
<p>PDE build likely needs some switches similar to those described above to manage
  the classpath computations.</p>
<h3>Manifest generator impact</h3>
<p>As mentioned above, the manifest generator will be updated to generate Export-InternalPackage:
  entries for every package /type that is not listed in the Export-Package header. </p>
<h3>Additional impacts</h3>
<p>All RCP plug-ins are expected to run correctly in strict mode. This means that
  their Export-Package list must include all API as well as any packages/classes
  which are known to be required by friendly plugins. Again, the Export-Package
  list is NOT a declaration of API. It is a visibility statement much like the
  public keyword in Java.</p>
<h3>Other notes</h3>
<p>The exact syntax of the package lists is open to change. The use of OSGi directives
  on the standard Export-Package header (for example) has been suggested. The
  various approaches have benefits and drawbacks and will be considered as an
  implementation detail. Here we note that the final syntax may not be as
  described above.</p>
<h2>Summary</h2>
<p>This proposal details the set of changes required to correctly and completely
  specify the public face (including API) of a plug-in. These changes are needed
  to allow Eclipse to run in a secure mode as well as facilitating various analysis
  techniques for security and performance optimization. The changes are quite
  modest and can be completed by related teams with limited effort.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>
